/*
    Copyright 2011 Peter Pratscher
 
    This file is part of Surveillance.NET.

    Surveillance.NET is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    Surveillance.NET is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Surveillance.NET. If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Net.Mail;
using System.Windows.Forms;
using AForge.Video.DirectShow;
using SurveillanceDotNet.AlarmActions;
using SurveillanceDotNet.Camera;
using SurveillanceDotNet.Model;
using SurveillanceDotNet.Model.RegularActions;
using SurveillanceDotNet.RegularActions;
using SurveillanceDotNet.Model.AlarmActions;

namespace SurveillanceDotNet
{
    public partial class MainForm : Form
    {
        Dictionary<SurveillanceCamera, string> _OpenCameras = new Dictionary<SurveillanceCamera, string>();

        public MainForm()
        {
            InitializeComponent();

            Database.Instance.MainGuiForm = this;
            Database.Instance.SurveillanceSystem.PropertyChanged += new PropertyChangedEventHandler(system_PropertyChanged);

            new FilterInfoCollection(FilterCategory.VideoCompressorCategory);

        }

        void system_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Status" && sender is SurveillanceSystem)
            {
                this.Invoke(new MethodInvoker(delegate
                {
                    lblSystemStatus.Text = ((SurveillanceSystem)sender).Status;
                }));
            }
        }

        private void btnAddCamera_Click(object sender, EventArgs e)
        {
            using (SurveillanceCameraForm frmCam = new SurveillanceCameraForm())
            {
                List<string> usedCams = new List<string>();

                foreach (SurveillanceCamera cam in Database.Instance.Cameras)
                {
                    usedCams.Add(cam.Name);
                }

                frmCam.CamerasInUse = usedCams;

                if (frmCam.ShowDialog() == DialogResult.OK)
                {
                    Database.Instance.Cameras.Add(frmCam.Camera);
                    UpdateSurveillanceCamDgv();
                }
            }
        }

        private void UpdateSurveillanceCamDgv()
        {
            dgvSurveillanceCameras.Rows.Clear();

            foreach (SurveillanceCamera cam in Database.Instance.Cameras)
            {
                dgvSurveillanceCameras.Rows.Add(new object[] {
                    cam.Name,
                    cam.Status
                });

                dgvSurveillanceCameras.Rows[dgvSurveillanceCameras.Rows.Count - 1].Tag = cam;
            }
        }

        private void editToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dgvSurveillanceCameras.SelectedRows.Count == 0) return;

            SurveillanceCamera editedCamera = (SurveillanceCamera)dgvSurveillanceCameras.SelectedRows[0].Tag;

            using (SurveillanceCameraForm frmCam = new SurveillanceCameraForm())
            {
                frmCam.Camera = editedCamera;

                if (frmCam.ShowDialog() == DialogResult.OK)
                {
                    UpdateSurveillanceCamDgv();
                }
            }
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dgvSurveillanceCameras.SelectedRows.Count == 0) return;

            SurveillanceCamera editedCamera = (SurveillanceCamera)dgvSurveillanceCameras.SelectedRows[0].Tag;
            Database.Instance.Cameras.Remove(editedCamera);
            UpdateSurveillanceCamDgv();
        }

        private void btnAddRegularAction_Click(object sender, EventArgs e)
        {
            using (RegularActionChoiceForm frm = new RegularActionChoiceForm())
            {
                if (frm.ShowDialog() == DialogResult.OK)
                {
                    UpdateRegularActionsList();
                }
            }
        }

        private void UpdateRegularActionsList()
        {
            dgvRegularActions.Rows.Clear();

            foreach (RegularAction action in Database.Instance.RegularActions)
            {
                dgvRegularActions.Rows.Add(new object[] {
                    action.Name,
                    action.Interval.ToString(),
                    action.Status
                });
                dgvRegularActions.Rows[dgvRegularActions.Rows.Count - 1].Tag = action;
            }
        }

        private void editRegularActionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dgvRegularActions.SelectedRows.Count == 0) return;

            RegularAction edited = (RegularAction)dgvRegularActions.SelectedRows[0].Tag;

            if (edited is EMailRegularAction)
            {
                using (EMailRegularActionForm frm = new EMailRegularActionForm())
                {
                    frm.Action = (EMailRegularAction)edited;
                    if (frm.ShowDialog() == DialogResult.OK)
                    {
                        UpdateRegularActionsList();
                    }
                }
            }
            if (edited is FTPPictureUploadRegularAction)
            {
                using (FtpRegularActionForm frm = new FtpRegularActionForm())
                {
                    frm.Action = (FTPPictureUploadRegularAction)edited;
                    if (frm.ShowDialog() == DialogResult.OK)
                    {
                        UpdateRegularActionsList();
                    }
                }
            }
        }

        private void removeRegularActionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dgvRegularActions.SelectedRows.Count == 0) return;

            RegularAction edited = (RegularAction)dgvRegularActions.SelectedRows[0].Tag;
            Database.Instance.RegularActions.Remove(edited);
            UpdateRegularActionsList();
        }

        private void eMailAccountsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (EMailManagementForm frmEMailManagement = new EMailManagementForm())
            {
                frmEMailManagement.ShowDialog();
            }
        }

        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnAddAlarmAction_Click(object sender, EventArgs e)
        {
            using (AlarmActionChoiceForm frm = new AlarmActionChoiceForm())
            {
                if (frm.ShowDialog() == DialogResult.OK)
                {
                    UpdateAlarmActionsList();
                }
            }
        }

        private void UpdateAlarmActionsList()
        {
            dgvAlarmActions.Rows.Clear();

            foreach (AlarmAction action in Database.Instance.AlarmActions)
            {
                dgvAlarmActions.Rows.Add(new object[] {
                    action.Name,
                    action.Code,
                    action.Status
                });

                dgvAlarmActions.Rows[dgvAlarmActions.Rows.Count - 1].Tag = action;
            }
        }

        private void editAlarmActionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dgvAlarmActions.SelectedRows.Count == 0) return;

            AlarmAction edited = (AlarmAction)dgvAlarmActions.SelectedRows[0].Tag;

            if (edited is EMailAlarmAction)
            {
                using (EMailAlarmActionForm frm = new EMailAlarmActionForm())
                {
                    frm.Action = (EMailAlarmAction)edited;
                    if (frm.ShowDialog() == DialogResult.OK)
                    {
                        UpdateAlarmActionsList();
                    }
                }
            }
            if (edited is FlashScreenAlarmAction)
            {
                using (FlaschScreenAlarmActionForm frm = new FlaschScreenAlarmActionForm())
                {
                    frm.Action = (FlashScreenAlarmAction)edited;
                    if (frm.ShowDialog() == DialogResult.OK)
                    {
                        UpdateAlarmActionsList();
                    }
                }
            }
            if (edited is PlaySoundAlarmAction)
            {
                using (PlaySoundAlarmActionForm frm = new PlaySoundAlarmActionForm())
                {
                    frm.Action = (PlaySoundAlarmAction)edited;
                    if (frm.ShowDialog() == DialogResult.OK)
                    {
                        UpdateAlarmActionsList();
                    }
                }
            }
            if (edited is SavePictureAlarmAction)
            {
                using (SaveFileAlarmForm frm = new SaveFileAlarmForm())
                {
                    frm.Action = (SavePictureAlarmAction)edited;
                    if (frm.ShowDialog() == DialogResult.OK)
                    {
                        UpdateAlarmActionsList();
                    }
                }
            }
            if (edited is RecordVideoAlarmAction)
            {
                using (RecordVideoAlarmActionForm frm = new RecordVideoAlarmActionForm())
                {
                    frm.Action = (RecordVideoAlarmAction)edited;
                    if (frm.ShowDialog() == DialogResult.OK)
                    {
                        UpdateAlarmActionsList();
                    }
                }
            }
        }

        private void removeAlarmActionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dgvAlarmActions.SelectedRows.Count == 0) return;

            AlarmAction edited = (AlarmAction)dgvAlarmActions.SelectedRows[0].Tag;
            Database.Instance.AlarmActions.Remove(edited);
            UpdateAlarmActionsList();
        }

        private void btnEnablSystem_Click(object sender, EventArgs e)
        {
            if (btnEnablSystem.Text == "ENABLE SYSTEM")
            {
                if (Database.Instance.Cameras.Count == 0)
                {
                    MessageBox.Show("Please define at least one surveillance camera!", "No camera", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                foreach (SurveillanceCamera camera in Database.Instance.Cameras)
                {
                    camera.PropertyChanged += new PropertyChangedEventHandler(camera_PropertyChanged);
                }

                foreach (AlarmAction action in Database.Instance.AlarmActions)
                {
                    action.PropertyChanged += new PropertyChangedEventHandler(alarmAction_PropertyChanged);
                }

                foreach (RegularAction action in Database.Instance.RegularActions)
                {
                    action.PropertyChanged += new PropertyChangedEventHandler(regularAction_PropertyChanged);
                }

                Database.Instance.SurveillanceSystem.StartSystem(Database.Instance.SystemStartTimeout);
                

                btnAddAlarmAction.Enabled = false;
                btnAddCamera.Enabled = false;
                btnAddRegularAction.Enabled = false;
                settingsToolStripMenuItem.Enabled = false;
                fileToolStripMenuItem.Enabled = false;

                btnEnablSystem.Text = "DISABLE SYSTEM";
            }
            else
            {
                Database.Instance.SurveillanceSystem.StopSystem();

                foreach (SurveillanceCamera camera in Database.Instance.Cameras)
                {
                    camera.PropertyChanged -= new PropertyChangedEventHandler(camera_PropertyChanged);
                }

                foreach (AlarmAction action in Database.Instance.AlarmActions)
                {
                    action.PropertyChanged -= new PropertyChangedEventHandler(alarmAction_PropertyChanged);
                }

                foreach (RegularAction action in Database.Instance.RegularActions)
                {
                    action.PropertyChanged -= new PropertyChangedEventHandler(regularAction_PropertyChanged);
                }

                btnAddAlarmAction.Enabled = true;
                btnAddCamera.Enabled = true;
                btnAddRegularAction.Enabled = true;
                settingsToolStripMenuItem.Enabled = true;
                fileToolStripMenuItem.Enabled = true;

                btnEnablSystem.Text = "ENABLE SYSTEM";
            }
        }

        void regularAction_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "Status" || !(sender is RegularAction)) return;

            RegularAction action = (RegularAction)sender;

            foreach (DataGridViewRow row in dgvRegularActions.Rows)
            {
                if (row.Tag == action)
                {
                    row.Cells[2].Value = action.Status;
                    return;
                }
            }
        }

        void alarmAction_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "Status" || !(sender is AlarmAction)) return;

            AlarmAction action = (AlarmAction)sender;

            foreach (DataGridViewRow row in dgvAlarmActions.Rows)
            {
                if (row.Tag == action)
                {
                    row.Cells[2].Value = action.Status;
                    return;
                }
            }
        }

        void camera_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "Status" || !(sender is SurveillanceCamera)) return;

            SurveillanceCamera camera = (SurveillanceCamera)sender;

            foreach (DataGridViewRow row in dgvSurveillanceCameras.Rows)
            {
                if (row.Tag == camera)
                {
                    row.Cells[1].Value = camera.Status;
                    return;
                }
            }

        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (Database.Instance.SurveillanceSystem.Status != "Stopped")
            {
                MessageBox.Show("You cannot close the application as long as the surveillance system is runnign!", "System running", MessageBoxButtons.OK, MessageBoxIcon.Error);
                e.Cancel = true;
            }
        }

        private void viewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dgvSurveillanceCameras.SelectedRows.Count == 0) return;

            SurveillanceCamera editedCamera = (SurveillanceCamera)dgvSurveillanceCameras.SelectedRows[0].Tag;

            if (!_OpenCameras.ContainsKey(editedCamera))
            {
                ViewCameraForm viewCameraForm = new ViewCameraForm();
                viewCameraForm.Camera = editedCamera;
                _OpenCameras.Add(editedCamera, "");
                viewCameraForm.FormClosed += new FormClosedEventHandler(viewCameraForm_FormClosed);
                viewCameraForm.Show();
            }

        }

        void viewCameraForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            SurveillanceCamera camera = ((ViewCameraForm)sender).Camera;
            _OpenCameras.Remove(camera);
        }

        private void cmsCameras_Opening(object sender, CancelEventArgs e)
        {
            if (Database.Instance.SurveillanceSystem.Status == "Stopped")
            {
                cmsCameras.Items[0].Visible = true;
                cmsCameras.Items[1].Visible = true;
                cmsCameras.Items[2].Visible = false;
            }
            else
            {
                cmsCameras.Items[0].Visible = false;
                cmsCameras.Items[1].Visible = false;
                cmsCameras.Items[2].Visible = true;
            }
        }

        private void cmsRegularActions_Opening(object sender, CancelEventArgs e)
        {
            e.Cancel = Database.Instance.SurveillanceSystem.Status != "Stopped";
        }

        private void cmsAlarmActions_Opening(object sender, CancelEventArgs e)
        {
            e.Cancel = Database.Instance.SurveillanceSystem.Status != "Stopped";
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                Database.Instance.SaveToFile(sfd.FileName);
            }
        }

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                Database.Instance.LoadFromFile(ofd.FileName, this, new PropertyChangedEventHandler(system_PropertyChanged));
                UpdateAlarmActionsList();
                UpdateRegularActionsList();
                UpdateSurveillanceCamDgv();
            }
        }

        private void systemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SystemConfigurationForm configForm = new SystemConfigurationForm();
            configForm.ShowDialog();
        }


    }
}
